home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1997 July: Mac OS SDK / Dev.CD Jul 97 SDK1.toast / Development Kits (Disc 1) / QuickDraw GX / Programming Stuff / Sample Code / Graphics Samples / mode ƒ / mode.c next >
Encoding:
C/C++ Source or Header  |  1996-04-15  |  21.2 KB  |  790 lines  |  [TEXT/KAHL]

  1. /**
  2.     File:          Mode.c
  3.  
  4.     Contents:    Creates a picture consisting of multi colored rectangles and rotates a 
  5.                 text shape over the top of the picture.  Menus allow the user to try 
  6.                 different transfer modes, colors, and update schemes.    
  7.  
  8.     The following filles are required to build this app:
  9.     
  10.                 mode.c, ColorLibrary.c, FontLibrary.c, GraphicsDebugLibrary.c,
  11.                 GraphicsLibrary.c, OffscreenLibrary.c, PictureLibrary.c, QDLibrary.c,  
  12.                 ShapeLibrary.c, TextLibrary.c, TransferModeLibrary.c, TransformLibrary.c. 
  13.     
  14.     Change History:
  15.  
  16.        4/96    bob        Updated #includes to support changed GX Library names.
  17.                     Changed fixed to Fixed.
  18.                     Updated the note regarding the files needed to run.
  19.                     Updated the copyright date.
  20.  
  21.      ©1991 - 1996 Apple Computer Inc. All Rights reserved 
  22. **/
  23.  
  24.  
  25. #include <Desk.h>
  26. #include <Events.h>
  27. #include <Fonts.h>
  28. #include <Menus.h>
  29. #include <Memory.h>
  30. #include <ToolUtils.h>
  31. #include <Windows.h>
  32.  
  33. #include "GraphicsLibraries.h"
  34. #include <GXErrors.h>
  35. #include <GXEnvironment.h>
  36. #include "FontLibrary.h"
  37. #include "OffscreenLibrary.h"
  38. #include "QDLibrary.h"
  39.  
  40. #include "mode.h"
  41.  
  42. /*______________________________________________________________________________________*/
  43. /*  Non-Shell Global Variables     */
  44.  
  45. Boolean        randColor, randXfer, updateDiff, macUpdate, useClip, eraseScreen;
  46. char        curXfer;
  47. commonColor    curColor;
  48. static char    lastXfer;
  49.  
  50.  
  51. /*______________________________________________________________________________________*/
  52. /*  Non-Shell Prototypes     */
  53. void    MakeTest(WindowPtr win);
  54. void    KillTest(WindowPtr win);
  55. void    MouseClickTest(WindowPtr win);
  56. void    KeyTest(WindowPtr win);
  57. void    IdleTest(WindowPtr win);
  58. void    UpdateTest(WindowPtr win);
  59.  
  60.  
  61. /*______________________________________________________________________________________*/
  62. /*  Shell Global Variables     */
  63.  
  64.     /*  Default window vars: */
  65. Str255        gWindowTitle     =  "\p Mode test ??";
  66. Rect        gWindowRect        = { 42,4,476,636 };
  67.  
  68. Boolean        gOuttaHere        = false;        /* Event loop cycles until this is TRUE         */
  69. short        gOptionOn        = false;        /* Is the option key being pressed?             */
  70. short        gCmdOn            = false;        /* Is the command key being pressed?             */
  71. Boolean        gWNEAvailable;                    /* Specifies if WaitNextEvent is available         */
  72. WindowPtr    gAppWindow;
  73. gxPoint        gLastPt;
  74.  
  75.  
  76. /*______________________________________________________________________________________*/
  77. void InitMac(void);
  78. void InitMac()
  79. {
  80.     EventRecord    theEvent;
  81.  
  82.     GXEnterGraphics();
  83.     
  84.     InitGraf(&qd.thePort);
  85.     InitFonts();
  86.     InitWindows();
  87.     InitCursor();
  88.  
  89.     gWNEAvailable = true;
  90.  
  91.     EventAvail(everyEvent,&theEvent);    /* Force windows to front… (for MF) */
  92. }
  93.  
  94.                                                         
  95. /*______________________________________________________________________________________*/
  96. WindowPtr CreateWindow(Str255, Rect *);
  97.  
  98. /*    CreateWindow takes a rect specification as well as a title string as parameters.  The 
  99. //    window is created with the specified title at the desired size.  NOTE: if a nil rectangle
  100. //    is passed the window is created the size of the startup monitor inset 20 pixels.
  101. */
  102.  
  103. WindowPtr CreateWindow(Str255 windowTitle, Rect *r)
  104. {
  105.     WindowPtr    theWindow;
  106.     Rect        theRect;
  107.     
  108.     if (r == nil) {
  109.         theRect.top        = qd.screenBits.bounds.top    + 50;
  110.         theRect.left    = qd.screenBits.bounds.left + 20;
  111.         theRect.bottom    = qd.screenBits.bounds.bottom - 20;
  112.         theRect.right    = qd.screenBits.bounds.right - 20;
  113.     }
  114.     else
  115.         theRect = *r;
  116.                 
  117.     theWindow = NewWindow(nil, &theRect, windowTitle, true, documentProc, (WindowPtr) -1L, false, 0L);
  118.  
  119.     GXIgnoreGraphicsNotice(transform_already_set);
  120.     SetDefaultViewPort(GXNewWindowViewPort(theWindow));
  121.     GXPopGraphicsNotice();
  122.     
  123.     SetPort(theWindow);
  124.     
  125.     return  theWindow;
  126. }
  127.  
  128.  
  129. /*______________________________________________________________________________________*/
  130. void InitAppMenus(void);
  131. void InitAppMenus()
  132. {    
  133.     short        i;
  134.     
  135.                 /*  Insert all app menus into the menu bar    */
  136.     for (i = 0;  i < mcMenuCount;  i++)                       
  137.         InsertMenu(GetMenu(mcFirstMenuID +i), AT_END);
  138.     
  139.                 /*  Insert all heirarchical menus into the menu bar    */
  140.     for (i = 0;  i < mcHeirCount;  i++)   
  141.         InsertMenu(GetMenu(mcFirstHeirID +i), AT_END);
  142.  
  143.                 /*    Add the DRVRs to the Apple Menu    */
  144.     AddResMenu(GetMHandle(mcAppleMenuID),'DRVR');
  145. }
  146.  
  147. /*______________________________________________________________________________________*/
  148. void AdjustMenus(void);
  149. void AdjustMenus()
  150. {    
  151. }
  152.  
  153.  
  154. /*______________________________________________________________________________________*/
  155. void DoGrowWindow(WindowPtr, EventRecord *);
  156. void DoGrowWindow(WindowPtr theWindow, EventRecord  *theEvent)
  157. {
  158.     long    newSize;
  159.     if (theWindow != FrontWindow()) 
  160.         SelectWindow(theWindow);
  161.     else
  162.         SetPort(theWindow);
  163.         
  164.     newSize = GrowWindow(theWindow,theEvent->where,&qd.screenBits.bounds);
  165.     if (newSize != 0)
  166.         SizeWindow(theWindow, LoWord(newSize), HiWord(newSize), true);
  167.     
  168. }
  169.  
  170.  
  171. /*______________________________________________________________________________________*/
  172. void DoMenuCommand(long);
  173. void DoMenuCommand(long    menuData)
  174. {
  175.     short        theMenu;
  176.     short        theItem;
  177.     Str255        theName;
  178.     short        theRefNum;
  179.  
  180.     static char    diffStr[] = "\pUse DiffShape";
  181.     static char    pictureStr[] = "\pUse Offscreen Background";
  182.  
  183.     Boolean        imageChanged = true;
  184.     OSErr        result         = noErr;
  185.     
  186.     
  187.     theMenu = HiWord(menuData);
  188.     theItem = LoWord(menuData);
  189.  
  190.     switch (theMenu)  {    
  191.         case mcAppleMenuID:
  192.             switch (theItem)  {
  193.                 case mcAbout:        break;
  194.                 default:
  195.                     GetItem(GetMHandle(mcAppleMenuID), theItem, theName);
  196.                     theRefNum = OpenDeskAcc(theName);
  197.                     break;
  198.             }
  199.             break;
  200.             
  201.         case mcFileMenuID:
  202.             switch ( theItem )  {
  203.                 case mcNew:            break;
  204.                 case mcOpen:        break;
  205.                 case mcClose:        break;
  206.                 case mcSave:        break;
  207.                 case mcSaveAs:        break;
  208.                 case mcPageSetUp:    break;
  209.                 case mcPrint:        break;
  210.                 case mcQuit:        gOuttaHere = true;        break;
  211.             }
  212.             break;
  213.  
  214.         case mcColorMenuID:
  215.             switch ( theItem )  {
  216.                 case ColorSpaceBarChanges:
  217.                     CheckItem(GetMHandle(mcColorMenuID), ColorSpaceBarChanges, true);
  218.                     CheckItem(GetMHandle(mcColorMenuID), ColorRandom, false);
  219.                     randColor = false;
  220.                     break;
  221.                 case ColorRandom:
  222.                     CheckItem(GetMHandle(mcColorMenuID), ColorSpaceBarChanges, false);
  223.                     CheckItem(GetMHandle(mcColorMenuID), ColorRandom, true);
  224.                     randColor = true;
  225.                     break;
  226.             }
  227.             break;
  228.  
  229.         case mcXferMenuID:
  230.             switch ( theItem )  {
  231.                 case gxCopyMode:
  232.                 case gxAddMode:
  233.                 case gxBlendMode:
  234.                 case gxMigrateMode:
  235.                 case gxMinimumMode:
  236.                 case gxMaximumMode:
  237.                 case gxHighlightMode:
  238.                 case gxAndMode:
  239.                 case gxOrMode:
  240.                 case gxXorMode:
  241.                 //LS  case pixelXorMode:
  242.                 case gxRampAndMode:
  243.                 case gxRampOrMode:
  244.                 case gxRampXorMode:
  245.                 case gxOverMode:
  246.                 case gxAtopMode:
  247.                 case gxExcludeMode:
  248.                 case gxFadeMode:
  249.                     CheckItem(GetMHandle(mcXferMenuID), curXfer, false);
  250.                     CheckItem(GetMHandle(mcXferMenuID), XferRandom, false);
  251.                     CheckItem(GetMHandle(mcXferMenuID), theItem, true);
  252.                     curXfer = theItem;
  253.                     randXfer = false;
  254.                     break;
  255.                 case XferRandom:
  256.                     CheckItem(GetMHandle(mcXferMenuID), XferRandom, true);
  257.                     CheckItem(GetMHandle(mcXferMenuID), curXfer, false);
  258.                     randXfer = true;
  259.                     break;
  260.             }
  261.             break;
  262.  
  263.         case mcUpdateMenuID:
  264.             switch ( theItem )  {
  265.                 case UpdatesUseDiffShape:
  266.                     updateDiff = (updateDiff) ? false : true;
  267.                     SetItem(GetMHandle(mcUpdateMenuID), UpdatesUseDiffShape, (ConstStr255Param)(updateDiff ? pictureStr : diffStr));
  268.                     eraseScreen = true;
  269.                     break;
  270.                 case UpdatesMacStyleUpdates:
  271.                     macUpdate = (macUpdate) ? false : true;
  272.                     CheckItem(GetMHandle(mcUpdateMenuID), UpdatesMacStyleUpdates, macUpdate);
  273.                     break;
  274.                 case UpdatesClipToTextBox:
  275.                     useClip = (useClip) ? false : true;
  276.                     CheckItem(GetMHandle(mcUpdateMenuID), UpdatesClipToTextBox, useClip);
  277.                     eraseScreen = true;
  278.                     break;
  279.             }
  280.             break;
  281.     }
  282.  
  283.     HiliteMenu(0);                    
  284. }
  285.  
  286.  
  287. /*______________________________________________________________________________________*/
  288. void DoMouseDown(EventRecord *);
  289. void DoMouseDown(EventRecord  *theEvent)
  290. {
  291.     short        thePart;
  292.     WindowPtr    theWindow;
  293.     register    i;
  294.  
  295.  
  296.     thePart = FindWindow(theEvent->where, &theWindow);
  297.     switch ( thePart )  {
  298.         case inMenuBar:    
  299.            AdjustMenus();
  300.            DoMenuCommand(MenuSelect(theEvent->where));
  301.            break;
  302.            
  303.         case inSysWindow:        
  304.            SystemClick( theEvent, theWindow );
  305.            break;
  306.            
  307.         case inContent:
  308.             {
  309.                 Point    QDpt;
  310.                 gxPoint    pt;
  311.                 
  312.                 
  313.                 GetMouse(&QDpt);
  314.                 
  315.                 pt.x = ff(QDpt.h);
  316.                 pt.y = ff(QDpt.v);
  317.                 MouseClickTest(theWindow);
  318.             }
  319.            
  320.                break;
  321.            
  322.         case inDrag:                
  323.             DragWindow(theWindow,theEvent->where,&qd.screenBits.bounds);
  324.             break;
  325.            
  326.         case inGrow:
  327.             DoGrowWindow(theWindow, theEvent);
  328.                break;
  329.            
  330.         case inZoomIn:
  331.         case inZoomOut:
  332.             if ( TrackBox(theWindow, theEvent->where, thePart) ) 
  333.                {
  334.                 SetPort(theWindow);                
  335.                 ZoomWindow(theWindow, thePart, true);    
  336.                 InvalRect(&theWindow->portRect);    
  337.                }
  338.             break;
  339.         }
  340. }
  341.  
  342.  
  343. /*______________________________________________________________________________________*/
  344. void DoKeyDown(EventRecord    *);
  345. void DoKeyDown(EventRecord    *theEvent)
  346. {
  347.     char        theKey;
  348.  
  349.     gCmdOn    = (theEvent->modifiers & cmdKey);
  350.     theKey     = theEvent->message & charCodeMask;
  351.  
  352.     if ((gCmdOn) && (theEvent->what == keyDown))  {
  353.         AdjustMenus();                        
  354.         DoMenuCommand(MenuKey(theKey));
  355.     }
  356.     KeyTest(gAppWindow);
  357. }
  358.  
  359.  
  360. /*______________________________________________________________________________________*/
  361. void DoEvent(EventRecord *);
  362. void DoEvent(EventRecord  *theEvent)
  363. {
  364.     switch (theEvent->what)  {
  365.         case nullEvent:
  366.             IdleTest(gAppWindow);
  367.             break;
  368.     
  369.         case mouseDown:    
  370.             DoMouseDown(theEvent);    
  371.             break;
  372.             
  373.         case keyDown:
  374.         case autoKey:    
  375.             DoKeyDown(theEvent);
  376.             break;
  377.             
  378.         case activateEvt:            
  379.         case updateEvt:
  380.             BeginUpdate(gAppWindow);
  381.                 UpdateTest(gAppWindow);
  382.             EndUpdate(gAppWindow);
  383.             break;
  384.             
  385.         case diskEvt:
  386.             break;
  387.         }
  388.  
  389. /*______________________________________________________________________________________*/
  390. void MainLoop(void);
  391. void MainLoop()
  392. {
  393.     EventRecord        theEvent;
  394.  
  395.     do  {
  396.         if (gWNEAvailable)
  397.             WaitNextEvent(everyEvent, &theEvent, 0, nil);
  398.         else  {
  399.             SystemTask();
  400.             GetNextEvent(everyEvent, &theEvent);
  401.             }
  402.         
  403.         DoEvent(&theEvent);
  404.         
  405.         } while (! gOuttaHere);
  406. }
  407.  
  408. /*______________________________________________________________________________________*/
  409. void main(void);
  410. void main()
  411. {
  412.     MaxApplZone();
  413.     MoreMasters(); MoreMasters(); MoreMasters();
  414.     MoreMasters(); MoreMasters(); MoreMasters();
  415.     
  416.     InitMac();                                                /*  Call desired initialization procedures. */            
  417.  
  418.     InitAppMenus();                                            /*  init and draw menu                         */
  419.     DrawMenuBar();    
  420.  
  421.     gAppWindow = CreateWindow(gWindowTitle, &gWindowRect);    /*  Create the application window. */                
  422.  
  423.     MakeTest(gAppWindow);
  424.     
  425.     gLastPt.x = gLastPt.y = ff(-1000);
  426.  
  427.     MainLoop();
  428.     
  429.     KillTest(gAppWindow);
  430.     DisposeWindow(gAppWindow);                                /*  Create the application window. */            
  431.     
  432.     GXExitGraphics();
  433. }
  434.  
  435.  
  436. /*______________________________________________________________________________________*/
  437.  
  438. void    setPictureXform(gxShape aPicture, gxTransform aTransform);
  439. gxShape    makeATextShape(char *sometext, Fixed x, Fixed y, Fixed thesize);
  440. void    undrawUsingDiff(void);
  441. void    undrawUsingOffscreen(void);
  442. void    invalShape(gxShape aShape);
  443. short    xrand(long max);
  444. void    xsrand(unsigned n);
  445.  
  446. gxShape        shPicture = nil, shText = nil, shTextBox = nil;
  447. gxShape        shPictureBox = nil, shMap = nil;
  448. offscreen    canvas;
  449.  
  450. /*______________________________________________________________________________________
  451.     set it all up,
  452. ______________________________________________________________________________________*/
  453. void    MakeTest(WindowPtr win)
  454. {
  455.     register    long    gxColorIndex;
  456.     register    short    x, y;
  457.     gxShape        grunt;
  458.     gxRectangle    bounds;
  459.     gxRectangle    r;
  460.     gxBitmap        bmap;
  461.  
  462.     randColor = randXfer = false;
  463.     updateDiff = true;
  464.     macUpdate = useClip = false;
  465.     curColor = violet;
  466.     curXfer = gxRampXorMode;
  467.     lastXfer = gxCopyMode;
  468.  
  469.     InitCommonColors();        /* to use the common colors library */
  470.     xsrand(38);                /* init the random seed */
  471.  
  472.     /* make a picture with repeating squares of different colors, by creating a picture shape */
  473.     /* and then adding a bunch of shapes to it. */
  474.  
  475.     shPicture = GXNewShape(gxPictureType);
  476.     GXSetShapeFill(shPicture, gxOpenFrameFill);
  477.     for (y=100, gxColorIndex = cyan; y <= 300; y += 50) {
  478.         for (x=150; x <= 350; x += 50, gxColorIndex += 4) {
  479.             grunt = NewShape4(gxRectangleType, ff(x), ff(y), ff(x + 50), ff(y + 50));
  480.             SetShapeCommonColor(grunt, gxColorIndex);
  481.             AddToShape(shPicture, grunt);
  482.             GXDisposeShape(grunt);
  483.         }
  484.     }
  485.         
  486.     /* make a text shape. set it up so that its gxTransform will be rotated and not the shape. */
  487.     shText = makeATextShape("Mødé Test", ff(75), ff(250), ff(96));
  488.     GXSetShapeAttributes(shText, gxMapTransformShape);
  489.     SetShapeCommonColor(shText, curColor);
  490.  
  491.     /*
  492.     // for onscreen updating:
  493.     //
  494.     // now make two gxRectangle shapes, each one having a gxRectangle corresponding to one of the
  495.     // two previous shapes we created.  these will be used to find the area of the text that
  496.     // is not over the picture (over the white background) so that this area can be drawn in
  497.     // white to "erase" the text before rotating and redrawing the text.
  498.     */
  499.  
  500.     GXGetShapeBounds(shText, 0, &bounds);
  501.     shTextBox = GXNewRectangle(&bounds);
  502.     GXSetShapePen(shTextBox, ff(1));
  503.     GXGetShapeBounds(shPicture, 0, &bounds);
  504.     shPictureBox = GXNewRectangle(&bounds);
  505.     GXSetShapePen(shPictureBox, ff(1));
  506.     
  507.     /*
  508.     // for offscreen updating:
  509.     //
  510.     // create a gxBitmap shape that is the size of the screen and as deep as the deepest
  511.     // monitor in our coordinate space.  the offscreen library copies our gxBitmap
  512.     // so we can dispose the one we created once the offscreen has been created.
  513.     // note: setting the map.image to nil will tell graphics to allocate the storage for the
  514.     // bits in it's gxHeap.  because we are not guaranteed that the gxHeap will be where we
  515.     // can modify it (it could be on an accelerator, for instance) we cannot get at the 
  516.     // image with GXGetBitmap().  if we want to have the image to modify we should allocate
  517.     // our own image.
  518.     */
  519.     {
  520.         gxBitmap        map;
  521.         gxPoint        pt = { 0, 0 };
  522.         Rect        bigRect = { -32767, -32767, 32767, 32767 };
  523.         GDHandle    gd = GetMaxDevice(&bigRect);
  524.         gxShape        shErase;
  525.         gxTransform    savedXform;
  526.     
  527.         map.width = (long)(win->portRect.right - win->portRect.left);
  528.         map.height = (long)(win->portRect.bottom - win->portRect.top);
  529.         map.pixelSize = (**(**gd).gdPMap).pixelSize;
  530.         map.rowBytes = 0L;
  531.         map.image = nil;
  532.         map.space = gxIndexedSpace;
  533.         map.profile = nil;
  534.         map.set = GXCloneColorSet(commonColorSet);
  535.         
  536.         shMap = GXNewBitmap(&map, &pt);
  537.         CreateOffscreen(&canvas, shMap);
  538.  
  539.         /* white out all bits in the offscreen */
  540.         GXGetShapeBounds(shMap, 1, &bounds);
  541.         shErase = GXNewRectangle(&bounds);
  542.         SetShapeCommonColor(shErase, gxWhite);
  543.         GXSetShapeTransform(shErase, canvas.xform);
  544.         GXDrawShape(shErase);
  545.         DisposeShapeAt(&shErase);
  546.         DisposeShapeAt(&shMap);
  547.  
  548.         /*
  549.         // set the gxTransform of our picture to the gxTransform of the offscreen
  550.         // which has its own gxViewPort.  any drawing of the picture shape will
  551.         // happen in the offscreen's gxViewPort, which has our bit shape as its gxBitmap.
  552.         // since our application allows us to switch between drawing the offscreen to 
  553.         // the screen, and actually drawing the picture, we need to set the picture's 
  554.         // gxTransform back so that we can draw it on the screen if we want to.
  555.         */
  556.  
  557.         savedXform = GXGetShapeTransform(shPicture);
  558.         setPictureXform(shPicture, canvas.xform);
  559.         GXDrawShape(shPicture);
  560.         setPictureXform(shPicture, savedXform);
  561.     }
  562. }
  563.  
  564.  
  565. void    UpdateTest(WindowPtr win)
  566. {
  567.     if (updateDiff)
  568.         GXDrawShape(shPicture);        /* draw the picture directly to the screen */
  569.     else
  570.         GXDrawShape(canvas.draw);        /* draw the offscreen to the screen */
  571.     GXDrawShape(shText);
  572. }
  573.  
  574.  
  575. /*______________________________________________________________________________________*/
  576. void    IdleTest(WindowPtr win)
  577. {    
  578.     if (randXfer) {                        /* flag tells us to change the transfer mode randomly */
  579.         curXfer = (char)xrand(gxFadeMode);
  580.         SetShapeCommonTransfer(shText, curXfer);
  581.     }
  582.     else if (lastXfer != curXfer) {        /* flag tells us to change the transfer mode */
  583.         lastXfer = curXfer;
  584.         SetShapeCommonTransfer(shText, curXfer);
  585.     }
  586.  
  587.     if (randColor) {                    /* flag tells us to change the common gxColor randomly */
  588.         curColor = (long)xrand(violet);
  589.         SetShapeCommonColor(shText, curColor);
  590.     }
  591.     
  592.     if (eraseScreen) {                    /* for cleaning up when user changes options */
  593.         EraseRect(&win->portRect);
  594.         UpdateTest(win);
  595.         eraseScreen = false;
  596.     }
  597.     else if (macUpdate) {                /* erase, invalidate & let the mac update mechanism draw it */
  598.         GrafPtr        savedPort;
  599.  
  600.         GetPort(&savedPort);
  601.         SetPort(win);
  602.         if (updateDiff)                    /* use diffshape to erase */
  603.             undrawUsingDiff();
  604.         else
  605.             undrawUsingOffscreen();        /* draw undrawUsingOffscreen to erase */
  606.         SetPort(savedPort);
  607.         
  608.         RotateShapeAboutCenter(shText, ff(15));
  609.         invalShape(shTextBox);
  610.         RotateShapeAboutCenter(shTextBox, ff(15));
  611.         invalShape(shTextBox);
  612.     }
  613.     else { 
  614.         if (updateDiff)                    /* use diffshape to erase */
  615.             undrawUsingDiff();
  616.         else
  617.             undrawUsingOffscreen();        /* use undrawUsingOffscreen to erase */
  618.         
  619.         RotateShapeAboutCenter(shText, ff(15));
  620.         GXDrawShape(shText);
  621.         RotateShapeAboutCenter(shTextBox, ff(15));
  622.     }
  623. }
  624.  
  625.  
  626. /*______________________________________________________________________________________
  627.     make a copy of the text box, which is always rotated to the same angle as the text.
  628.     diff it with the picture recatngle, and then draw it (its gxColor is already set to
  629.     white).  then draw the picture to "erase" the text over it, rotate the text and 
  630.     draw the text, and rotate the text box shape to keep it in synch with the text shape.
  631. ______________________________________________________________________________________*/
  632. void undrawUsingDiff(void)
  633. {
  634.     gxRectangle    bounds;
  635.     gxShape        shSaveClip;
  636.     gxShape        shFoo = CopyShape(shTextBox);
  637.     
  638.     GXDifferenceShape(shFoo, shPictureBox);
  639.     SetShapeCommonColor(shFoo, gxWhite);
  640.  
  641.     if (useClip) {
  642.         shSaveClip = GXGetShapeClip(shPictureBox);
  643.         GXSetShapeClip(shPicture, shTextBox);
  644.     }
  645.     GXDrawShape(shFoo);
  646.     GXDrawShape(shPicture);
  647.     if (useClip) {
  648.         GXSetShapeClip(shPicture, shSaveClip);
  649.         DisposeShapeAt(&shSaveClip);
  650.     }
  651.     GXDisposeShape(shFoo);
  652. }
  653.  
  654.  
  655. /*______________________________________________________________________________________
  656.     draw the offscreen with or without a clip.
  657. ______________________________________________________________________________________*/
  658. void undrawUsingOffscreen(void)
  659. {
  660.     gxShape        shSaveClip;
  661.  
  662.     if (useClip) {
  663.         shSaveClip = GXGetShapeClip(canvas.draw);
  664.         GXSetShapeClip(canvas.draw, shTextBox);
  665.     }
  666.     GXDrawShape(canvas.draw);
  667.     if (useClip) {
  668.         GXSetShapeClip(canvas.draw, shSaveClip);    /* restore offscreen's clip */
  669.         DisposeShapeAt(&shSaveClip);
  670.     }
  671. }
  672.  
  673.  
  674. /*______________________________________________________________________________________*/
  675. void    MouseClickTest(WindowPtr win)
  676. {
  677.     while(Button());
  678. }
  679.  
  680.  
  681. /*______________________________________________________________________________________*/
  682. void    KeyTest(WindowPtr win)
  683. {
  684.     curColor += 1;
  685.     if (curColor > apple_blue)
  686.         curColor = gxBlack;
  687.     SetShapeCommonColor(shText, curColor);
  688. }
  689.  
  690.  
  691. /*______________________________________________________________________________________*/
  692. void    KillTest(WindowPtr win)
  693. {
  694.     DisposeOffscreen(&canvas);
  695.     DisposeShapeAt(&shPicture);
  696.     DisposeShapeAt(&shText);
  697.     DisposeShapeAt(&shTextBox);
  698.     DisposeShapeAt(&shPictureBox);
  699.     DisposeShapeAt(&shMap);
  700.     DisposeCommonColors();
  701. }
  702.  
  703.  
  704. /*______________________________________________________________________________________
  705.     pretty simple - a smarter version would check the shapeType and recursively
  706.     traverse sub-pictures.
  707. ______________________________________________________________________________________*/
  708. void setPictureXform(gxShape aPicture, gxTransform aTransform)
  709. {
  710.     register    long    i;
  711.     
  712.     GXSetShapeTransform(aPicture, aTransform);
  713.     for (i=GXGetPicture(aPicture, nil, nil, nil, nil); i != 0; i--) {
  714.         GXSetShapeTransform(GetPictureItem(aPicture, i, nil, nil, nil, nil), aTransform);
  715.     }
  716. }
  717.  
  718. /*______________________________________________________________________________________
  719.     create a qd region that spans all the points on the shape and invalidate that region.
  720. ______________________________________________________________________________________*/
  721. void invalShape(gxShape aShape)
  722. {
  723.     register    long    i, last, numberOfPointsInShape;
  724.     gxPoint        pt, fixedStartPt;
  725.     Point        qdStartPt, qdPt;
  726.     RgnHandle    aRgn = NewRgn();
  727.     
  728.     numberOfPointsInShape = GXCountShapePoints(aShape, 1L);
  729.  
  730.     GetShapeIndexPoint(aShape, 1, &fixedStartPt);
  731.     
  732.     FixedPointToShort(&fixedStartPt, &qdStartPt);
  733.     
  734.     OpenRgn();
  735.         MoveTo(qdStartPt.h, qdStartPt.v);
  736.         for (i = 2; i <= numberOfPointsInShape; i++) {
  737.             GetShapeIndexPoint(aShape, i, &pt); 
  738.                 
  739.             FixedPointToShort(&pt, &qdPt);
  740.             LineTo(qdPt.h, qdPt.v);
  741.         }
  742.         LineTo(qdStartPt.h, qdStartPt.v);
  743.     CloseRgn(aRgn);
  744.     
  745.     InvalRgn(aRgn);
  746.     DisposeRgn(aRgn);
  747. }
  748.  
  749.  
  750. /*______________________________________________________________________________________*/
  751. gxShape makeATextShape(char *sometext, Fixed x, Fixed y, Fixed thesize)
  752. {
  753.     gxPoint    where;
  754.     gxShape    thetext;
  755.     
  756.     where.x = x;
  757.     where.y = y;
  758.     thetext = NewCString(sometext,&where);
  759.     
  760.     GXSetShapeTextSize(thetext,thesize);
  761.     SetShapeCommonFont(thetext, timesFont);
  762.     return(thetext);
  763. }
  764.  
  765.  
  766. /* ripped from the ansi library */
  767.  
  768. static unsigned long seed = 1;
  769.  
  770. short    xrand(long max)
  771. {
  772.     short    foo;
  773.  
  774.     seed = seed * 1103515245 + 12345;
  775.     asm {
  776.         move.w    seed,d0            ;  high word of long
  777.         andi.w    #0x7FFF,d0        ;  remove high bit
  778.         move.w    d0,foo            ;  needs futher processing
  779.     }
  780.     while(foo > max)            /* not very clever (or correct), but it was fast and easy */
  781.         foo = foo >> 1;
  782.     return(foo);
  783. }
  784.  
  785.  
  786. void    xsrand(unsigned n)
  787. {
  788.     seed = n;
  789. }